#include "Inf_MQTT.h"

#include "esp_log.h"
#include "mqtt_client.h"
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>

#define TAG "mqtt"
#define MQTT_URL "mqtt://192.168.55.43" // MQTT连接地址
#define MQTT_PORT 1883                  // MQTT连接端口号
#define MQTT_CLIENT_ID "esp32"          // Client ID（设备唯一）

#define MQTT_PUBLIC_TOPIC "/test/topic1"    // 测试用的,推送消息主题
#define MQTT_SUBSCRIBE_TOPIC "/test/topic2" // 测试用的,需要订阅的主题

static void log_error_if_nonzero(const char *message, int error_code) {
    if (error_code != 0) {
        ESP_LOGE(TAG, "Last error %s: 0x%x", message, error_code);
    }
}

esp_mqtt_client_handle_t client;

// mqtt连接事件处理函数
static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) {
    ESP_LOGD(TAG, "Event dispatched from event loop base=%s, event_id=%" PRIi32 "", base, event_id);

    esp_mqtt_event_handle_t event = event_data;
    client = event->client;

    int msg_id;
    switch ((esp_mqtt_event_id_t)event_id) {
    case MQTT_EVENT_CONNECTED: // 连接成功
        ESP_LOGI(TAG, "连接成功");

        // 发布一条消息到/test/topic1主题
        msg_id = esp_mqtt_client_publish(client, MQTT_PUBLIC_TOPIC, "hzd is handsome", 0, 1, 0);
        ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);

        // 连接成功后，订阅测试主题
        esp_mqtt_client_subscribe_single(client, MQTT_SUBSCRIBE_TOPIC, 0);

        // msg_id = esp_mqtt_client_subscribe(client, "/topic/qos0", 0); // 订阅主题
        // msg_id = esp_mqtt_client_unsubscribe(client, "/topic/qos1"); // 解订阅主题
        break;
    case MQTT_EVENT_DISCONNECTED: // 连接断开
        ESP_LOGI(TAG, "连接断开");
        break;

    case MQTT_EVENT_SUBSCRIBED: // 订阅成功-收到订阅消息ACK
        ESP_LOGI(TAG, "订阅成功, msg_id=%d", event->msg_id);
        // msg_id = esp_mqtt_client_publish(client, "/topic/qos0", "data", 0, 0, 0);
        // ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
        break;
    case MQTT_EVENT_UNSUBSCRIBED: // 取消订阅成功-收到解订阅消息ACK
        ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
        break;
    case MQTT_EVENT_PUBLISHED: // 发布成功-收到发布消息ACK
        // ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
        break;
    case MQTT_EVENT_DATA: // 收到数据
        ESP_LOGI(TAG, "MQTT_EVENT_DATA");
        ESP_LOGE("Receive", "TOPIC=%.*s", event->topic_len, event->topic);
        ESP_LOGE("Receive", "DATA=%.*s", event->data_len, event->data);
        break;
    case MQTT_EVENT_ERROR: // 错误
        ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
        if (event->error_handle->error_type == MQTT_ERROR_TYPE_TCP_TRANSPORT) {
            log_error_if_nonzero("reported from esp-tls", event->error_handle->esp_tls_last_esp_err);
            log_error_if_nonzero("reported from tls stack", event->error_handle->esp_tls_stack_err);
            log_error_if_nonzero("captured as transport's socket errno", event->error_handle->esp_transport_sock_errno);
            ESP_LOGI(TAG, "Last errno string (%s)", strerror(event->error_handle->esp_transport_sock_errno));
        }
        break;
    default:
        // ESP_LOGI(TAG, "Other event id:%d", event->event_id);
        break;
    }
}

void Inf_MQTT_Init(void) {
    esp_mqtt_client_config_t mqtt_cfg = {
        .broker.address.uri = MQTT_URL,         // MQTT连接地址
        .broker.address.port = MQTT_PORT,       // MQTT连接端口号
        .credentials.client_id = MQTT_CLIENT_ID // Client ID
    };

    // 设置mqtt配置，返回mqtt操作句柄
    esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);
    // 注册mqtt事件回调函数
    esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
    // 启动mqtt连接
    esp_mqtt_client_start(client);
}

void Inf_MQTT_Transimit(char *data) {
    esp_mqtt_client_publish(client, MQTT_PUBLIC_TOPIC, data, 0, 1, 0);
}
